#ifndef CAMERA_H
#define CAMERA_h

#include "Vector3.hpp"
#include "Matrix4.hpp"

class Camera
{
//private:
//	Vector3 e, d, up;
//
//	Matrix4 rinv, tinv, inv,  cameraMatrix;

public:
		Vector3 e, d, up;

	Matrix4 rinv, tinv, inv,  cameraMatrix;
	//constructors
	Camera(Vector3& e, Vector3& d, Vector3& up):e(e), d(d), up(up) {
		Vector3 zC = (e-d).normalize();
		std::cout << "e: " << e.getx() <<" " <<  e.gety() << " " << e.getz() << std::endl;
		std::cout << "d: " << d.getx() <<" " <<  d.gety() << " " << d.getz() << std::endl;
		std::cout << "up: " << up.getx() <<" " <<  up.gety() << " " << up.getz() << std::endl;
		Vector3 xC = up.cross(zC).normalize();
		Vector3 yC = zC.cross(xC);
		std::cout << "xC: " << xC.getx() <<" " <<  xC.gety() << " " << xC.getz() << std::endl;
		std::cout << "yC: " << yC.getx() <<" " <<  yC.gety() << " " << yC.getz() << std::endl;
		std::cout << "zC: " << zC.getx() <<" " <<  zC.gety() << " " << zC.getz() << std::endl;

		rinv.set(
			xC.getx(), yC.getx(), zC.getx(), 0,
			xC.gety(), yC.gety(), zC.gety(), 0,
			xC.getz(), yC.getz(), zC.getz(), 0,
			0, 0, 0, 1);
		tinv.set(
			1, 0, 0, 0,
			0, 1, 0, 0,
			0, 0, 1, 0,
			-e.getx(), -e.gety(), -e.getz(), 1);

		inv = tinv.mult(rinv);
		
		//inv.set(
		//	xC.getx(), yC.getx(), zC.getx(), 0,
		//	xC.gety(), yC.gety(), zC.gety(), 0,
		//	xC.getz(), yC.getz(), zC.getz(), 0,
		//	-e.getx(), -e.gety(), -e.getz(), 1);

		cameraMatrix.set(
			xC.getx(), xC.gety(), xC.getz(), 0,
			yC.getx(), yC.gety(), yC.getz(), 0,
			zC.getx(), zC.gety(), zC.getz(), 0,
			e.getx(), e.gety(), e.getz(), 1);
	}

	//getters
	Vector3& gete() {
		return e;
	}
	Vector3& getd() {
		return d;
	}
	Vector3& getup() {
		return up;
	}
	Matrix4& getCamera() {
		return cameraMatrix;
	}
	Matrix4& getInverse() {
		return inv;
	}

	//setter (only one, this was done purposefully)
	void set(Vector3& e, Vector3& d, Vector3& up) {
		this->e = e;
		this->d = d;
		this->up = up;

		Vector3 zC = (d-e).normalize();
		Vector3 xC = up.cross(zC).normalize();
		Vector3 yC = zC.cross(xC);

		rinv.set(
			xC.getx(), yC.getx(), zC.getx(), 0,
			xC.gety(), yC.gety(), zC.gety(), 0,
			xC.getz(), yC.getz(), zC.getz(), 0,
			0, 0, 0, 1);
		tinv.set(
			1, 0, 0, 0,
			0, 1, 0, 0,
			0, 0, 1, 0,
			-e.getx(), -e.gety(), -e.getz(), 1);

		inv = tinv.mult(rinv);
		
		//inv.set(
		//	xC.getx(), yC.getx(), zC.getx(), 0,
		//	xC.gety(), yC.gety(), zC.gety(), 0,
		//	xC.getz(), yC.getz(), zC.getz(), 0,
		//	-e.getx(), -e.gety(), -e.getz(), 1);

		cameraMatrix.set(
			xC.getx(), zC.gety(), xC.getz(), 0,
			yC.getx(), yC.gety(), yC.getz(), 0,
			zC.getx(), zC.gety(), zC.getz(), 0,
			e.getx(), e.gety(), e.getz(), 1);
	}
};



#endif